#!/usr/bin/env python
# coding: utf-8

# In[ ]:





# In[ ]:





# In[ ]:





# In[ ]:





# In[17]:


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, StratifiedKFold, cross_val_score
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (accuracy_score, precision_score, recall_score, f1_score, 
                             confusion_matrix, classification_report, roc_curve, auc, 
                             RocCurveDisplay, ConfusionMatrixDisplay)
from sklearn.utils.class_weight import compute_class_weight
from sklearn.multiclass import OneVsRestClassifier
from collections import Counter

# 设置中文字体和图形样式
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")

# 1. 加载数据
def load_data(file_path):
    """加载数据集"""
    data = pd.read_csv(file_path)
    print("数据集形状:", data.shape)
    return data

# 2. 数据探索和预处理
def explore_data(data):
    """数据探索"""
    print("=== 数据基本信息 ===")
    print(data.info())
    
    print("\n=== 前5行数据 ===")
    print(data.head())
    
    print("\n=== 数值特征统计 ===")
    print(data.describe())
    
    print("\n=== 缺失值检查 ===")
    print(data.isnull().sum())
    
    return data

# 3. 处理类别不平衡
def handle_class_imbalance(y):
    """处理类别不平衡问题"""
    print("\n=== 类别分布分析 ===")
    class_distribution = Counter(y)
    print("类别分布:", class_distribution)
    
    # 计算类别权重
    class_weights = compute_class_weight('balanced', classes=np.unique(y), y=y)
    print("类别权重:", dict(zip(np.unique(y), class_weights)))
    
    return class_weights

# 4. 手动分割数据集
def split_dataset(data, target_column='Class', test_size=0.3, random_state=42):
    """手动分割训练集和测试集"""
    X = data.drop(columns=[target_column])
    y = data[target_column]
    
    # 分割数据集
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=test_size, random_state=random_state, stratify=y
    )
    
    print(f"训练集形状: {X_train.shape}, 测试集形状: {X_test.shape}")
    return X_train, X_test, y_train, y_test

# 5. 数据预处理
def preprocess_data(X_train, X_test):
    """数据预处理"""
    # 处理缺失值
    imputer = SimpleImputer(strategy='mean')
    X_train_imputed = imputer.fit_transform(X_train)
    X_test_imputed = imputer.transform(X_test)
    
    # 标准化特征
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train_imputed)
    X_test_scaled = scaler.transform(X_test_imputed)
    
    return X_train_scaled, X_test_scaled, scaler

# 6. 训练多种分类模型
def train_models(X_train, y_train):
    """训练多种分类模型"""
    models = {
        'RandomForest': RandomForestClassifier(random_state=42, class_weight='balanced'),
        'SVM': SVC(random_state=42, probability=True, class_weight='balanced'),
        'LogisticRegression': LogisticRegression(random_state=42, class_weight='balanced', max_iter=1000)
    }
    
    # 十折交叉验证
    print("\n=== 十折交叉验证结果 ===")
    for name, model in models.items():
        cv_scores = cross_val_score(model, X_train, y_train, cv=10, scoring='accuracy')
        print(f"{name} 平均准确率: {cv_scores.mean():.4f} (±{cv_scores.std():.4f})")
    
    # 训练最终模型
    trained_models = {}
    for name, model in models.items():
        model.fit(X_train, y_train)
        trained_models[name] = model
    
    return trained_models

# 7. 评估模型性能
def evaluate_models(models, X_test, y_test):
    """评估模型性能"""
    results = {}
    
    for name, model in models.items():
        y_pred = model.predict(X_test)
        y_proba = model.predict_proba(X_test) if hasattr(model, 'predict_proba') else None
        
        results[name] = {
            'accuracy': accuracy_score(y_test, y_pred),
            'precision': precision_score(y_test, y_pred, average='weighted'),
            'recall': recall_score(y_test, y_pred, average='weighted'),
            'f1': f1_score(y_test, y_pred, average='weighted'),
            'confusion_matrix': confusion_matrix(y_test, y_pred),
            'y_proba': y_proba
        }
        
        print(f"\n=== {name} 分类报告 ===")
        print(classification_report(y_test, y_pred))
    
    return results

# 8. 绘制混淆矩阵热力图
def plot_confusion_matrix_heatmap(cm, model_name, classes):
    """绘制混淆矩阵热力图"""
    plt.figure(figsize=(10, 8))
    disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=classes)
    disp.plot(cmap='Blues', values_format='d')
    plt.title(f'{model_name} - 混淆矩阵热力图')
    plt.ylabel('真实标签')
    plt.xlabel('预测标签')
    plt.xticks(rotation=45)
    plt.tight_layout()
    plt.show()

# 9. 绘制ROC曲线和计算AUC（支持多分类）
def plot_roc_curve_multiclass(y_test, y_proba, model_name, classes):
    """绘制多分类ROC曲线"""
    n_classes = len(classes)
    
    # 计算每个类别的ROC曲线和AUC
    fpr = dict()
    tpr = dict()
    roc_auc = dict()
    
    for i in range(n_classes):
        fpr[i], tpr[i], _ = roc_curve(y_test == i, y_proba[:, i])
        roc_auc[i] = auc(fpr[i], tpr[i])
    
    # 计算宏平均ROC曲线和AUC
    all_fpr = np.unique(np.concatenate([fpr[i] for i in range(n_classes)]))
    mean_tpr = np.zeros_like(all_fpr)
    for i in range(n_classes):
        mean_tpr += np.interp(all_fpr, fpr[i], tpr[i])
    mean_tpr /= n_classes
    fpr["macro"] = all_fpr
    tpr["macro"] = mean_tpr
    roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])
    
    # 绘制所有ROC曲线
    plt.figure(figsize=(10, 8))
    plt.plot(fpr["macro"], tpr["macro"],
             label=f'宏平均 ROC曲线 (AUC = {roc_auc["macro"]:.2f})',
             color='navy', linestyle=':', linewidth=4)
    
    colors = plt.cm.rainbow(np.linspace(0, 1, n_classes))
    for i, color in zip(range(n_classes), colors):
        plt.plot(fpr[i], tpr[i], color=color, lw=2,
                 label=f'{classes[i]} (AUC = {roc_auc[i]:.2f})')
    
    plt.plot([0, 1], [0, 1], 'k--', lw=2)
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.xlabel('假正率')
    plt.ylabel('真正率')
    plt.title(f'{model_name} - 多分类ROC曲线')
    plt.legend(loc="lower right")
    plt.show()
    
    return roc_auc

# 主函数
def main():
    # 加载数据
    data = load_data('land_train.csv')
    
    # 数据探索
    data = explore_data(data)
    
    # 分割数据集
    X_train, X_test, y_train, y_test = split_dataset(data)
    
    # 处理类别不平衡
    class_weights = handle_class_imbalance(y_train)
    
    # 数据预处理
    X_train_scaled, X_test_scaled, scaler = preprocess_data(X_train, X_test)
    
    # 编码目标变量
    label_encoder = LabelEncoder()
    y_train_encoded = label_encoder.fit_transform(y_train)
    y_test_encoded = label_encoder.transform(y_test)
    classes = label_encoder.classes_
    
    # 训练模型
    models = train_models(X_train_scaled, y_train_encoded)
    
    # 评估模型
    results = evaluate_models(models, X_test_scaled, y_test_encoded)
    
    # 绘制混淆矩阵热力图
    for name, result in results.items():
        plot_confusion_matrix_heatmap(result['confusion_matrix'], name, classes)
    
    # 绘制ROC曲线（支持多分类）
    for name, result in results.items():
        if result['y_proba'] is not None:
            plot_roc_curve_multiclass(y_test_encoded, result['y_proba'], name, classes)

if __name__ == "__main__":
    main()


# In[ ]:




